Code
from IPython.display import display, HTML
display(HTML("""
<style>
.container { width: '100%',
transition: 'concave'}
</style>
"""))---
title: "UNICEF Global Youth Mortality Report"
format:
html:
embed-resources: true
code-fold: true
theme: cosmo
css: styles.css
execute:
enabled: true
jupyter: python3
---from IPython.display import display, HTML
display(HTML("""
<style>
.container { width: '100%',
transition: 'concave'}
</style>
"""))import pandas as pd
from plotnine import *
from mizani.formatters import comma_format
import plotly.express as px
# Load your data
df = pd.read_csv("unicef_indicator_1.csv")
meta = pd.read_csv("unicef_metadata.csv")
# Filter latest year + relevant indicator
latest_year = df['time_period'].max()
df_deaths_world = df[
(df['indicator'] == 'Deaths aged 5 to 24') &
(df['time_period'] == latest_year) &
(df['sex'] == 'Total')
]
# Merge with metadata
df_map = df_deaths_world.merge(meta[['country', 'alpha_3_code']], on='country', how='left')
df_map.rename(columns={"alpha_3_code_y": "alpha_3_code"}, inplace=True)
df_map.drop(columns=["alpha_3_code_x"], errors="ignore", inplace=True)
df_map['obs_value'] = pd.to_numeric(df_map['obs_value'], errors='coerce')
# Create choropleth map
world_map = px.choropleth(
df_map,
locations='alpha_3_code',
color='obs_value',
hover_name='country',
color_continuous_scale='Blues',
projection='natural earth',
labels={
'alpha_3_code': 'Country_Code',
'obs_value': 'Total Death'
}
)
world_map.update_layout(
autosize=True,
margin=dict(t=40, l=0, r=0, b=0),
dragmode=False,
geo=dict(
projection_type='natural earth',
showcoastlines=True,
showframe=False,
showcountries=True,
fitbounds="locations",
projection_scale=1,
center=dict(lat=0, lon=0)
)
)
# Convert charts to HTML
map_html = world_map.to_html(include_plotlyjs='cdn', full_html=False)
# Display with full-width stacked layout
display(HTML(f"""
<style>
body {{
margin: 0;
font-family: Arial, sans-serif;
background-color: #c1d0d4
}}
.dashboard-vertical {{
flex-direction: column;
gap: 10px;
padding: 20px;
max-width: 100%;
box-sizing: border-box;
}}
.chart-box {{
background-color: #5883a6;
border: 2px solid #5883a6;
padding: 15px;
text-align: center;
}}
.h2,.p{{
font-family: Arial, sans-serif;
color: white;
}}
</style>
<div class="dashboard-vertical">
<div class="chart-box">
<h2 class="h2">Youth Mortality by Country (Ages 5–24) – 2022</h2>
<p class="p">Displays global distribution of youth deaths by country of latest year</p>
{map_html}
</div>
</div>
"""))Displays global distribution of youth deaths by country of latest year
# ─────────────────────────────────────────────
# 2. Bar Chart (Top 10 countries with highest deaths)
# ─────────────────────────────────────────────
# Calculate total deaths across all years
df_deaths_bar = df[df['indicator'] == 'Deaths aged 5 to 24']
df_deaths_bar= df_deaths_bar[df_deaths_bar['sex'] == 'Total']
top10_total_deaths = (
df_deaths_bar.groupby('country')['obs_value']
.sum()
.sort_values(ascending=False)
.head(10)
.reset_index()
)
top10_total_deaths = top10_total_deaths.merge(
df_deaths_bar[['country', 'alpha_3_code']].drop_duplicates(),
on='country',
how='left'
)
top10_total_deaths["obs_value_millions"] = top10_total_deaths["obs_value"] / 1e6
top10_sorted = top10_total_deaths.sort_values(by='alpha_3_code')
# Plot the chart
bar_chart_plotly = px.bar(
top10_sorted,
x='alpha_3_code',
y='obs_value_millions',
text=top10_sorted["obs_value_millions"].round(1),
color='country',
labels={
'alpha_3_code': 'Country_Code',
'obs_value_millions': 'Total Deaths (in Millions)'
},
template='plotly_white'
)
bar_chart_plotly.update_traces(
textposition='outside',
marker=dict(line=dict(color='grey', width=1))
)
bar_chart_plotly.update_layout(
yaxis=dict(title='Total Deaths (in Millions)'),
xaxis=dict(title='Country', categoryorder='array', categoryarray=top10_sorted['alpha_3_code']),
margin=dict(t=50, b=50),
# width=700,
#height=400
)
bar_html = bar_chart_plotly.to_html(include_plotlyjs=False, full_html=False)
# Display with full-width stacked layout
display(HTML(f"""
<div class="dashboard-vertical">
<div class="chart-box">
<h2 class="h2">Top 10 Countries by Total Death Rate</h2>
<p class="p">Highlights countries with the highest total youth deaths of all time</p>
{bar_html}
</div>
</div>
"""))Highlights countries with the highest total youth deaths of all time
# ─────────────────────────────────────────────
# 3. Scatterplot + Regression (Deaths vs GDP per Capita)
# ─────────────────────────────────────────────
# STEP 1: Get Top 10 Countries by Population
meta_clean = meta.dropna(subset=['Population'])
meta_clean = meta_clean.drop_duplicates(subset='country', keep='first')
meta_top10 = meta_clean.sort_values(by='Population', ascending=False).head(10)
# STEP 2: Filter death data for 'Total' (all years)
df_deaths_total_scatter = df[
(df['indicator'] == 'Deaths aged 5 to 24') &
(df['sex'] == 'Total') &
(df['country'].isin(meta_top10['country']))
]
# STEP 3: Sum total deaths across all years
df_deaths_sum = df_deaths_total_scatter.groupby('country', as_index=False)['obs_value'].sum()
df_deaths_sum.rename(columns={'obs_value': 'total_deaths'}, inplace=True)
# STEP 4: Merge with population
df_scatter = df_deaths_sum.merge(meta_top10[['country', 'Population']], on='country', how='left')
# STEP 5: Convert to millions and clean
df_scatter['Population_M'] = pd.to_numeric(df_scatter['Population'], errors='coerce') / 1e6
df_scatter['Deaths_M'] = pd.to_numeric(df_scatter['total_deaths'], errors='coerce') / 1e6
df_scatter = df_scatter.dropna()
# STEP 6: Plot with Regression Line
scatter_plot = px.scatter(
df_scatter,
x='Population_M',
y='Deaths_M',
color='country',
hover_name='country',
trendline='ols', # Adds regression line
hover_data={
'Population_M': ':.2f',
'Deaths_M': ':.2f'
},
labels={
'Population_M': 'Population (Millions)',
'Deaths_M': 'Total Deaths (Millions)',
'country': 'Country'
},
template='simple_white'
)
scatter_plot.update_traces(marker=dict(size=15))
scatter_html = scatter_plot.to_html(include_plotlyjs=False, full_html=False)
# Display with full-width stacked layout
display(HTML(f"""
<div class="dashboard-vertical">
<div class="chart-box">
<h2 class="h2">Deaths vs Birth</h2>
<p class="p">Top 10 Death vs Birth comparison of all the time</p>
{scatter_html}
</div>
</div>
"""))
Top 10 Death vs Birth comparison of all the time
# ─────────────────────────────────────────────
# 4. Time Series Chart (global average over years)
# ─────────────────────────────────────────────
df_deaths_time_series = df[
(df['indicator'] == 'Deaths aged 5 to 24') &
(df['sex'] == 'Total')
][['country', 'time_period', 'obs_value']].copy()
df_deaths_time_series.rename(columns={'obs_value': 'death_rate'}, inplace=True)
# STEP 2: Get Birth Rate from meta
df_births = meta[['country', 'time_period', 'birth_rate']].dropna().copy()
# STEP 3: Merge both on country + year
df_combined = pd.merge(df_deaths_time_series, df_births, on=['country', 'time_period'], how='inner')
# STEP 4: Group each separately by year
df_birth_yearly = df_combined.groupby('time_period', as_index=False)['birth_rate'].mean()
df_death_yearly = df_combined.groupby('time_period', as_index=False)['death_rate'].mean()
df_death_yearly['death_rate'] = df_death_yearly['death_rate'] / 1e3 # convert to Thousands
birth_hover = px.line(
df_birth_yearly,
x='time_period',
y='birth_rate',
markers=True,
labels={
'time_period': 'Year',
'birth_rate': 'Births per 1,000 People'
},
template='simple_white'
)
birth_hover.update_traces(
hovertemplate='Year: %{x}<br>Birth Rate: %{y:.2f}',
line=dict(color='green'),
marker=dict(color='black', size=8)
)
death_hover = px.line(
df_death_yearly,
x='time_period',
y='death_rate',
markers=True,
labels={
'time_period': 'Year',
'death_rate': 'Deaths (in Thousands)'
},
template='simple_white',
# width=700,
# height=400
)
death_hover.update_traces(
hovertemplate='Year: %{x}<br>Deaths: %{y:.2f}K',
line=dict(color='crimson'),
marker=dict(color='black', size=8)
)
death_html = death_hover.to_html(include_plotlyjs=False, full_html=False)
# Display with full-width stacked layout
display(HTML(f"""
<div class="dashboard-vertical">
<div class="chart-box">
<h2 class="h2">Global Youth Death Rate </h2>
<p class="p">Shows how youth death rates have changed year by year across all the countries</p>
{death_html}
</div>
</div>
"""))
birth_html = birth_hover.to_html(include_plotlyjs=False, full_html=False)
# Display with full-width stacked layout
display(HTML(f"""
<div class="dashboard-vertical">
<div class="chart-box">
<h2 class="h2">Global Youth Birth Rate </h2>
<p class="p">Shows how youth birth rates have changed year by year across all the countries</p>
{birth_html}
</div>
</div>
"""))Shows how youth death rates have changed year by year across all the countries
Shows how youth birth rates have changed year by year across all the countries